/** WMI NETWORK TOOLS
*	JScript interfaces for WMI Network Functions
*		version 0.9 (1.25.2008)
*		Matthew Smith
*		http://digivation.net/programming/networktools/
*
* Simplified ways to work with the network using WMI and JScript
* allows for reading of certain network configuration items, and a few
* operations.
*
*	Version History
*	1.0	x.x.xxxx		first public release
*
* Depends on wmiRegistryTools.js! Without this library, networkToolsGetProxySettings()
* and networkToolsSetProxySettings() will not function
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/** GET IP ADDRESS OF COMPUTER
* INPUTS: takes a string variable of the computer name. use "." for local
* OUTPUTS: returns the IP address as a string
*/
function networkToolsGetIP(computer) {
	var WMIService = GetObject("winmgmts:\\\\" + computer + "\\root\\CIMV2"); // connect to WMI service
	var colNics = WMIService.ExecQuery("Select * From Win32_NetworkAdapter Where AdapterType = 'Ethernet 802.3'"); // find all ethernet adapters.
	var enumNics = new Enumerator(colNics); // to look through them, we must Enumerate the collection returned by the above query
	// let's loop through all the adapters. Currently this only returns a single string value, so we're only
	// returning the IP address of the LAST adapter. To be really correct, we should have an array and return the
	// device ID and IP address, to support multiple adapters. There could also be some logic to find out if it's connected.
	for (; !enumNics.atEnd(); enumNics.moveNext()) {
		var objNic = enumNics.item(); // get the current object
		//WScript.Echo("The DeviceID is: " + objNic.DeviceID); // debug statement
		var colNicConfigs = WMIService.ExecQuery("ASSOCIATORS OF {Win32_NetworkAdapter.DeviceID='" + objNic.DeviceID + "'} WHERE AssocClass=Win32_NetworkAdapterSetting"); // get the adapter settings collection related to the current device ID retrieved in the prior query
		var enumNicConfigs = new Enumerator(colNicConfigs); // enumerate all the settings!
		// let's step through the settings...
		while( !enumNicConfigs.atEnd()) {
			var objNicConfigs = enumNicConfigs.item(); // get the current NIC configs
			// heres some handy code from the great internets... it seems that our WMI interface returns pesky VBArrays that must be
			// converted... this was a headache to figure out!
			// this loop assembles the octets of the IP address array
			if( objNicConfigs.IPAddress != null ) {
				var IPArray = VBArray(objNicConfigs.IPAddress).toArray(); // had to find this trick ;)
				//WScript.Echo(IPArray[0]); // debug statement
			}
			enumNicConfigs.moveNext(); // move to next item
			// if its the last item, lets send it back.
			// we should really have compiled an array from the above and return that array here... but whatever
			if( enumNicConfigs.atEnd() ) {
				return IPArray[0];
			}
		}
	}
}

/** GET MAC ADDRESS
* INPUT: computer name as string, for local use "."
* OUTPUT: string with MAC address
*/
function networkToolsGetMAC(computer) {
	var WMIService = GetObject("winmgmts:\\\\" + computer + "\\root\\CIMV2"); // connect to WMI
	var colNics = WMIService.ExecQuery("Select * From Win32_NetworkAdapter Where AdapterType = 'Ethernet 802.3'"); // find all ethernet adapters
	var enumNics = new Enumerator(colNics); // enumerate the collection found above (usually a single adapter, unless there are multiple adapters in the machine
	// step through adapters
	for(; !enumNics.atEnd(); enumNics.moveNext()) {
		var objNic = enumNics.item(); // get the current adapter
		// WScript.Echo("MAC ADDRESS: " + objNic.MACAddress); // debug statement ;)
		// we should really collect all the strings for all adapters and return an array (so that we can use the script with multiple adapters)
		// this will be a feature for later, for now we grab the last one:
		if( enumNics.atEnd ) {
			return objNic.MACAddress;
		}
	}
}

/**GET NETWORK SETTINGS
* INPUT: function(arg1,arg2) => arg1 = computer name as string, use "." for local | arg2 => string to retrieve, use one of following"
*	String				Returns			Type
*    =============================================================
*	DHCP_Enabled			t=yes, f=no			bool
*	DNS_Domain			the domain			string
*	DNS_Host_Name			computer host name	string
*	IP					ip address			string
*	MAC					mac address		string
*    =============================================================
* OUTPUT: see above
*/
function networkToolsGetNetSettings(computer, param) {
	var WMIService = GetObject("winmgmts:\\\\" + computer + "\\root\\CIMV2"); // connect to WMI service
	var colNics = WMIService.ExecQuery("Select * From Win32_NetworkAdapter Where AdapterType = 'Ethernet 802.3'"); // find all ethernet adapters.
	var enumNics = new Enumerator(colNics); // to look through them, we must Enumerate the collection returned by the above query
	// let's loop through all the adapters. Currently this only returns a single string value, so we're only
	// returning the IP address of the LAST adapter. To be really correct, we should have an array and return the
	// device ID and IP address, to support multiple adapters. There could also be some logic to find out if it's connected.
	for (; !enumNics.atEnd(); enumNics.moveNext()) {
		var objNic = enumNics.item(); // get the current object
		//WScript.Echo("The DeviceID is: " + objNic.DeviceID); // debug statement
		var colNicConfigs = WMIService.ExecQuery("ASSOCIATORS OF {Win32_NetworkAdapter.DeviceID='" + objNic.DeviceID + "'} WHERE AssocClass=Win32_NetworkAdapterSetting"); // get the adapter settings collection related to the current device ID retrieved in the prior query
		var enumNicConfigs = new Enumerator(colNicConfigs); // enumerate all the settings!
		// let's step through the settings...
		while( !enumNicConfigs.atEnd()) {
			var objNicConfigs = enumNicConfigs.item(); // get the current NIC configs
			enumNicConfigs.moveNext(); // move to next item, for some reason we have to move before testing in this branch
			// if its the last item, lets send it back.
			// we should really have compiled an array from the above and return that array here... but whatever
			if( enumNicConfigs.atEnd() ) {
				// lets locate and return the property requested
				switch( param ) {
					default:
						break;
					case "DHCP_Enabled":
						return objNicConfigs.DHCPEnabled;
					case "DNS_Domain":
						return objNicConfigs.DNSDomain;
					case "DNS_Host_Name":
						return objNicConfigs.DNSHostName;
				}
			}
		}
	}
}

/** ENABLE DHCP ON MACHINE
* currently applies to ALL adapters!!!
* INPUT: name of computer as string, use "." for local machine
* OUTPUT: nothing
*/
function networkToolsEnableDHCP(computer) {
	var WMIService = GetObject("winmgmts:\\\\" + computer + "\\root\\CIMV2"); // connect to WMI
	var colNetAdapters = WMIService.ExecQuery("Select * From Win32_NetworkAdapterConfiguration Where IPEnabled = TRUE"); // find all network configs
	var enumNetAdapters = new Enumerator(colNetAdapters);
	var retErr = 0;
	
	// this currently enables DHCP for ALL adapters!
	while( !enumNetAdapters.atEnd() ) {
		var objNetAdapter = enumNetAdapters.item(); // get current adapter
		retErr = objNetAdapter.EnableDHCP();
		enumNetAdapters.moveNext();
	}
}

/** JOIN A DOMAIN
* joins the computer to the specified domain
* INPUT: computer as string, use "." for local
* OUTPUT: none
* 					WARNING ::: UNTESTED CODE!!!! NEEDS TESTING ON XP, DOES NOT WORK ON 2K
*/
function networkToolsJoinDomain(computer, domain) {
	var WMIService = GetObject("winmgmts:\\\\" + computer + "\\root\\CIMV2"); // connect to WMI
	var colComputer = WMIService.ExecQuery("SELECT * FROM Win32_ComputerSystem"); // get the computer
	var enumComputer = new Enumerator(colComputer); // we have to enumerate the collection but there should only be one result
	var objComputer = enumComputer.item(); // get computer object .. there should only be one... no looping for now.
	
	// now let's do stuff!
	// error checking: 
	if( !domain ) { WScript.Echo("Error: You must provide a domain"); return; }
	WScript.Echo(" attempting to join " + computer + " to the " + domain + " domain.");
	objComputer.JoinDomainOrWorkgroup(domain); // THIS DOESNT WORK ON W2K AND ISNT TESTED YET ON XP
}

/** GET PROXY SETTINGS
* INPUTS: arg1 = computer as string, arg2 = function as string, see table
* reads proxy settings - this function has calls to the registry tools, so wmiRegistryTools.js needs to be in the same directory
*	String				Returns			Type
*    =============================================================
*	Proxy_Enabled			t=yes, f=no			bool
*	Proxy_Server			the server			string
*	Proxy_Override			override domains		string
*	
*    =============================================================
*/
eval(includeExtJS("wmiRegistryTools.js")); // load the registry tools

function networkToolsGetProxySettings(computer, param) {
	var regKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; // where we're looking
	switch( param ) {
		default:
			WScript.Echo("error with function syntax, check your code");
			return;
		case "Proxy_Enabled":
			var status = registryToolsReadValue(computer, "HKLM", regKey, "ProxyEnable", "REG_DWORD"); // read the value
			if( status == 0x1 ) { return true; }
			if( status == 0x0 ) { return false; }
			else { break; }
		case "Proxy_Server":
			var server = registryToolsReadValue(computer, "HKLM", regKey, "ProxyServer", "REG_SZ"); // read value
			return server;
		case "Proxy_Override":
			var override = registryToolsReadValue(computer, "HKLM", regKey, "ProxyOverride", "REG_SZ"); // read value
			return override;
	}
}

/** SET PROXY SETTINGS
* changes proxy settings - this function has calls to the registry tools, so wmiRegistryTools.js needs to be in the same directory
* INPUTS: arg1 = computer as string, arg2 = operation, see below, arg3 = new setting
*	String				Type			Set
*    ==================================================
*	Proxy_Enabled			bool			true => enabled
*	Proxy_Server			string		ip:port
*	Proxy_Override			string		<local> for local addresses, 
*									semicolon seperated values
*    ==================================================
*/
function networkToolsSetProxySettings(computer, param, data) {
	var regKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; // where we're looking
	switch( param ) {
		default:
			WScript.Echo("error with function syntax, check your code");
			return;
		case "Proxy_Enabled":
			if( data == true ) { var state = 0x1; }
			else if( data == false ) { var state = 0x0; }
			else { return -1; }
			registryToolsWriteValue(computer, "HKLM", regKey, "ProxyEnable", "REG_DWORD", state); // write value
			return;
		case "Proxy_Server":
			registryToolsWriteValue(computer, "HKLM", regKey, "ProxyServer", "REG_SZ", data); // write value
			return;
		case "Proxy_Override":
			registryToolsWriteValue(computer, "HKLM", regKey, "ProxyOverride", "REG_SZ", data); // write value
			return;
	}
}

/** Include Function
* Allows for the inclusion of external JS libraries
* call using eval( includeExtJS(fileName) );
* the include statment must occur before the first call to an external routine
*/
function includeExtJS(fileName) {
	var fso = new ActiveXObject('Scripting.FileSystemObject'); // create the file system object
	if( !fso.FileExists(fileName) ) { return -1; } // check for file existance and fail if no file
	var file = fso.OpenTextFile(fileName); // open file
	var stream = file.ReadAll(); // read file
	file.Close(); // close file
	return stream; // send it back (you need to evaluate the return)
}